/**
 * Author       :       Kang, JulKi
 * E-mail       :       jkkang65@@hanmail.net
 * 
 * Ver		:	1.51
 * 
 * Last updated 2011. 9. 22 
 * Copyleft () 2011, All rights is not reserved..
 */

import  java.awt.*;
import  java.awt.event.*;
import	java.awt.Color;
import  javax.swing.*;
import	javax.swing.event.*;
import  javax.swing.JSlider;
import	javax.swing.JProgressBar;
import	javax.swing.border.TitledBorder;

import	java.net.*;
import	java.io.*;

import	java.lang.*;
import	java.util.*;
import	java.util.Hashtable;
import	java.util.Enumeration;

class MySlider extends JSlider implements ChangeListener
{
	TitledBorder	tb;
	int		nSleepSec = 3;
	
	//public MySlider(int min, int max, int value)
	public MySlider(int min, int max)
	{
		//super(min, max, value);
		super(min, max);

	        setMinorTickSpacing(1);
	        setMajorTickSpacing(5);
		setPaintTicks(true);
	        setPaintLabels(true);
	        
	        tb = new TitledBorder("Sleep : " + this.getSleepSec() + " (sec)");
	        System.out.println("jk first time : " + this.getSleepSec());
	        
	        tb.setTitleJustification(TitledBorder.RIGHT);
	        setBorder(tb);
	        
	        addChangeListener(this);

	        // slider.setBorder(new TitledBorder(str));
	}
	
	public void stateChanged(ChangeEvent e)
	{
		JSlider source = (JSlider)e.getSource();
		
		this.nSleepSec = (int)source.getValue();
		
		if (this.nSleepSec == 0) {
			setSleepSec(1);
			this.setValue(getSleepSec());
		}
		
		System.out.println("> slider(sleep) : " + getSleepSec());
		tb.setTitle("Sleep : " + getSleepSec() + " (sec) ");

	}
	
	public void setTitleBorder(int sec)
	{
		tb.setTitle("Sleep : " + sec + " (sec) ");
	}
	
	public int getSleepSec()
	{
		return nSleepSec;
	}
	
	public void setSleepSec(int sec)
	{
		nSleepSec = sec;
	}
}

class MyFrame extends JFrame implements ActionListener, WindowListener
{
	ServerSocket	ss = null;
	Socket		sc;
	//InputStream	is;
	//OutputStream	os;
	int		iPortNum = 20111;
	final int	iSliderMin = 0;
	final int	iSliderMax = 20;
		
	JButton         exitButton = new JButton("Exit");
	JProgressBar	jProgressBar;
	JLabel		jLabel1, jLabel2;
	//	MySlider	slider = new MySlider(0, 10, 5);
        
//	MySlider	mySlider = new MySlider(0, 10, 5);
	MySlider	mySlider = new MySlider(iSliderMin, iSliderMax);
        JButton[]	jGridButton; 

        JPanel          pGrid;
        JPanel          pMenu;

        Dimension       screen;
        Dimension       f_size;
        int		xPos, yPos;
        
        int		nGridX, nGridY;
        int		nSteps;
        int		nLiveCells;
        int		iSleepSec;
        byte[]		pBuf;
        
        Hashtable<String,String>	ht = new Hashtable<String,String>();

        public MyFrame () throws IOException
        {
                //d = new Dimension(x, y);
                screen = Toolkit.getDefaultToolkit().getScreenSize();

                socketInit();	// Socket startup                
                //eventAdd();        // Event add or Thread add

                //setResizable(false);
                //this.setVisible(true);

                //super.pack();
        }
        
         public void drawFrame()
         {
      	       	this.setSize(600, 600);
                this.setTitle("Hello, My JFrame : " + getGridX() + "x" + getGridY() + "  Step (" + getNSteps() + ")");

                Container cp = this.getContentPane();

                cp.setBackground(new Color(Color.white.getRGB()));
                cp.setLayout(new BorderLayout());
                  
                cp.add((pGrid = new JPanel()), BorderLayout.CENTER);
                cp.add((pMenu = new JPanel()), BorderLayout.SOUTH);
                //pMenu = new JPanel();
                //pMenu.setPreferredSize(new Dimension(150, 30));
                //cp.add(pMenu, BorderLayout.SOUTH);
        
                pGrid.setLayout(new GridLayout(getGridX(), getGridY()));
        
                //pMenu.setLayout(new GridLayout(1, 3));
                //pMenu.setLayout(new GridLayout(1, 2));
                pMenu.setLayout(new GridLayout(2, 2));

                jProgressBar = new JProgressBar(0, getNSteps());
                //jProgressBar = new JProgressBar();
                //jProgressBar.setMinimum(0);
                //jProgressBar.setMaximum(getNSteps());
                jProgressBar.setValue(0);
                jProgressBar.setStringPainted(true);	// print 0% ~ 100%
                jProgressBar.setBorder(BorderFactory.createTitledBorder("Processing..."));
                pMenu.add(jProgressBar);
               
                //mySlider = new MySlider(0, 10, 5);
                pMenu.add(mySlider);
                pMenu.add(exitButton);
                
        	JPanel pLabel = new JPanel();
                pMenu.add(pLabel);
                
	        TitledBorder tbjLabel = new TitledBorder("Game Of Life Info");
	        tbjLabel.setTitleJustification(TitledBorder.RIGHT);

                //jLabel.setBorder(BorderFactory.createTitledBorder("GOL Info..."));
                pLabel.setBorder(tbjLabel);
                pLabel.setLayout(new GridLayout(2, 1));
                
                //jLabel1 = new JLabel("Live Cells : ", JLabel.RIGHT);                
                jLabel1 = new JLabel("     Steps :  ", JLabel.RIGHT);
                jLabel2 = new JLabel("     Live Cells :  ", JLabel.RIGHT);
                
                //jLabel1.setHorizontalAlignment(JLabel.RIGHT);
                //jLabel2.setHorizontalAlignment(JLabel.RIGHT);
                
               //pMenu.add(jLabel);
                pLabel.add(jLabel1);
                pLabel.add(jLabel2);
                

                jGridButton = new JButton[getGridX() * getGridY()];
                
        	for (int i=0; i<getGridXY(); i++) {
                	//System.out.println("i. = " + Integer.toString(i));

                	jGridButton[i] = new JButton();
                	pGrid.add(jGridButton[i]);
        
                	jGridButton[i].setBackground(new Color(255, 0, 0));
                }
             
        	f_size = this.getSize();

                this.xPos = (int)(screen.getWidth() / 2 - f_size.getWidth() / 2);
                this.yPos = (int)(screen.getHeight() / 2 - f_size.getHeight() / 2);
                
                setLocation(this.xPos, this.yPos);
                setResizable(false);
		setVisible(true);
		eventAdd();		
		//super.pack();
        }
        
        public void changeButtonColor(int step)
        {
        	this.setTitle("Hello, My JFrame : " + getGridX() + "x" + getGridY() + "  Step (" + step + "/" + getNSteps() + ")");
                
        	//System.out.println("gridSize = " + gridSize);
        	
        	for (int i=0; i<getGridXY(); i++) {
                	if (pBuf[i]-48 == 0)	jGridButton[i].setBackground(new Color(Color.lightGray.getRGB()));
                	else			jGridButton[i].setBackground(new Color(Color.darkGray.getRGB()));
                }
        }
        
        public void eventAdd()
        {
                this.addWindowListener(this);
                exitButton.addActionListener(this);
                //yes_bt.addActionListener(this);
                //can_bt.addActionListener(this);
        }

        public void socketInit()	 throws IOException 
        {
        	boolean		isFirst = true;
        	String		msg;

        	// try {
      			//boolean flag = true;
       			//Hashtable<String, String>	ht = new Hashtable<String, String>();
       			//Hashtable	ht = new Hashtable();
        	//Enumeration	en;
       			
        	ss = new ServerSocket(iPortNum);
        	
        	System.out.println("\n> Server Started...");
        	//System.out.println("Server with Port(" + iPortNum + ") is ready...");
        	//System.out.println("Connection waiting...");

       		while (true) {
       	        	int		step = 1;
       	        	
       	       		System.out.println("> Server with Port(" + iPortNum + ") is ready...");
       	       		System.out.println("> Connection waiting...");

			sc = ss.accept();
			System.out.println("> " + sc.getInetAddress() + " connected...");
			
			//is = sc.getInputStream();
			
			BufferedReader br = new BufferedReader(new InputStreamReader(sc.getInputStream()));
			// jkkang's check
			BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(sc.getOutputStream()));
			
			/*
			 * get stream data from socket
			 */
			while ((msg = br.readLine()) != null) {
				String[] parsing = msg.split(" ");

				System.out.println("read> nstep = " + step);
				System.out.println("read> parsing[0] = " + parsing[0]);
				System.out.println("read> parsing[1] = " + parsing[1]);
												
				if (parsing[0].equals("sleep_sec") || parsing[0].equals("nsteps") || parsing[0].equals("grid_x") || parsing[0].equals("grid_y") || parsing[0].equals("live_cells")) {
					// save key & value at the hash table
					ht.put(parsing[0], parsing[1]);
					
					if (parsing[0].equals("nsteps")) {
						setNSteps(Integer.parseInt((String)ht.get("nsteps")));
						
						if (isFirst == false) {
							jProgressBar.setMinimum(0);
							jProgressBar.setMaximum(getNSteps());
						}
					}
					else if (parsing[0].equals("sleep_sec")) {
						mySlider.setValue(Integer.parseInt((String)ht.get("sleep_sec")));
						mySlider.setSleepSec(Integer.parseInt((String)ht.get("sleep_sec")));
						mySlider.setTitleBorder(mySlider.getSleepSec());
						System.out.println("> sleep sec : " + mySlider.getSleepSec());
					}
					else if (parsing[0].equals("grid_x")) {
						setGridX(Integer.parseInt((String)ht.get("grid_x")));
					}
					else if (parsing[0].equals("grid_y")) {
						setGridY(Integer.parseInt((String)ht.get("grid_y")));
					}
					else if (parsing[0].equals("live_cells")) {
						setLiveCells(Integer.parseInt((String)ht.get("live_cells")));
						jLabel1.setText("     Steps :  " + (step-1));
						jLabel2.setText("     Live Cells :  " + getLiveCells());
					}
			        }
				
				if (parsing[0].equals("grid_data")) {
					if (isFirst == true) {
						drawFrame();
						isFirst = false;
					}

					pBuf = parsing[1].getBytes();
		       			/*
		       			for (int i=0; i<parsing[1].length(); i++) {
		       	        		int num = pBuf[i] - 48;
		       	        		System.out.println("pBuf[" + i + "] = " + num);
		       	        	}
		       				
		       			System.exit(0);
		       	        	*/
					//System.out.println("changeButtonColor");
					changeButtonColor(step);
					step++;
					
			                jProgressBar.setValue(step);
					bw.write("sleep " + mySlider.getSleepSec() + "\n");
					bw.flush();
					System.out.println("\nwrite> sleep = " + mySlider.getSleepSec() + "\n");
				}
			}

			System.out.println("\nmsg> while(msg = br.readLine()) == null, so exit while()");
			
			//System.out.println("is.close(), sc.close(), ss.close()");
			System.out.println("msg> GOL step is finished...");
			System.out.println("\n");
			
			br.close();
			bw.close();
			sc.close();
       		}
		//ss.close();

		//catch  (IOException e) {
       		//	e.printStackTrace();
       		//}
        }
  
        public int getNSteps()
        {
        	return	nSteps;
        }
 
        public void setNSteps(int n)
        {
        	nSteps = n;
        }

        public int getLiveCells()
        {
        	return	nLiveCells;
        }
        
        public void setLiveCells(int n)
        {
        	nLiveCells = n;
        }
        
        public int getGridX()
        {
        	return	nGridX;
        	//return Integer.parseInt((String)ht.get("grid_x"));
        }
        
        public void setGridX(int n)
        {
        	nGridX = n;
	}
        public int getGridY()
        {
        	return	nGridY;
        	//return Integer.parseInt((String)ht.get("grid_y"));
        }

        public void setGridY(int n)
        {
        	nGridY = n;
        }
        
        public int getGridXY()
        {
        	return	getGridX() * getGridY();
        }
        
        public void actionPerformed(ActionEvent e)
        {
                if (e.getSource() == exitButton)
                {
                        System.out.println("> Exit Button pressed...");
                        System.out.println("> The application finished...");
                        System.exit(0);
                }
        	/*
                if (e.getSource() == yes_bt)
                {
                        System.out.println("> Ok button pressed...");
                }
                else if (e.getSource() == can_bt)
                {
                        System.out.println("> Exit button pressed...");
                }
                */
        }

        public void windowClosing(WindowEvent e)
        {
                System.out.println("> System control button pressed to exit...");
                System.exit(0);
        }
        
        public void windowClosed(WindowEvent e) {}
        public void windowOpened(WindowEvent e) {}
        public void windowActivated(WindowEvent e) {}
        public void windowDeactivated(WindowEvent e) {}
        public void windowIconified(WindowEvent e) {}
        public void windowDeiconified(WindowEvent e) {}
}

/**
 * 
 * @@author jkkang
 *
 * start of Main()
 */
public class MyFrameMain
{
        public static void main(String [] args) throws IOException
        {
                MyFrame myFrame = new MyFrame();
        }
}
